package org.lewis.core.dao;

import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.lewis.core.domain.Page;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

/**
 * 通用Dao
 * 
 * @author taiqichao
 */
@Repository
public class DaoSupport extends HibernateDaoSupport {
	
	protected final Log logger = LogFactory.getLog(getClass());
	
	protected final static int QUERY_MAX_SIZE = 1000;

	public void save(Object pojo) {
		getHibernateTemplate().save(pojo);
	}

	public Object get(Class<?> entityClass, long id) {
		return getHibernateTemplate().get(entityClass, id);
	}

	public void remove(Class<?> entityClass, long id) {
		getHibernateTemplate().delete(get(entityClass, id));
	}

	public void update(Object pojo) {
		getHibernateTemplate().update(pojo);
	}

	public void executeUpdate(String hql, Object... parms) {
		Query query = this.buildQuery(hql, parms);
		query.executeUpdate();
	}

	public void executeUpdate(final String hql,
			Map<String, Comparable<?>> params) {
		Query query = this.buildQuery(hql, params);
		query.executeUpdate();
	}

	public List<?> list(String hql, Object... parms) {
		return this.list(hql, false, parms);
	}

	public List<?> list(final String hql, boolean cacheable, Object... parms) {
		Query query = this.buildQuery(hql, parms);
		query.setCacheable(cacheable);
		return query.list();
	}

	public List<?> list(final String hql, Map<String, Comparable<?>> params) {
		return this.list(hql, false, params);
	}

	public List<?> list(final String hql, boolean cacheable,
			Map<String, Comparable<?>> params) {
		Query query = this.buildQuery(hql, params);
		query.setCacheable(cacheable);
		List<?> list=query.list();
		if(null!=list&&list.size()>=QUERY_MAX_SIZE){
			logger.error("Query rows must be less than "+QUERY_MAX_SIZE+" rows !");
		}
		return list;
	}

	public Page<?> listPage(final String hql, Page<?> page, Object... parms) {
		return this.listPage(hql, page, false, parms);
	}

	@SuppressWarnings("unchecked")
	public Page<?> listPage(final String hql, Page<?> page, boolean cacheable,
			Object... parms) {
		Query query = this.buildQuery(hql, parms);
		query.setFirstResult(page.getStartIndex());
		query.setMaxResults(page.getSize());
		query.setCacheable(cacheable);
		page.setResult(query.list());
		page.setTotalCount(getObjectCount(hql, parms));
		return page;
	}

	@SuppressWarnings("unchecked")
	public Page<?> listPage(final String hql, Page<?> page,
			Map<String, Comparable<?>> params) {
		Query query = this.buildQuery(hql, params);
		query.setFirstResult(page.getStartIndex());
		query.setMaxResults(page.getSize());
		page.setResult(query.list());
		page.setTotalCount(getObjectCount(hql, params));
		return page;
	}

	/**
	 * 构建Query
	 * 
	 * @param hql
	 *            HQL
	 * @param parms
	 *            参数数组
	 * @return Query
	 */
	protected Query buildQuery(final String hql, Object... parms) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < parms.length; i++) {
			query.setParameter(i, parms[i]);
		}
		return query;
	}

	private Query buildQuery(final String hql, Map<String, Comparable<?>> params) {
		Query query = getSession().createQuery(hql);
		for (Map.Entry<?, ?> entry : params.entrySet()) {
			query.setParameter(entry.getKey().toString(), entry.getValue());
		}
		return query;
	}

	public long getObjectCount(final String hql, Object... parms) {
		String queryString = "from " + StringUtils.substringAfter(hql, "from");
		queryString = StringUtils.substringBefore(queryString, "order by");
		queryString = "select count(id) " + queryString;
		Query query = this.buildQuery(queryString, parms);
		long recTotal = ((Long) query.iterate().next()).longValue();
		return recTotal;
	}

	public long getObjectCount(final String hql,
			Map<String, Comparable<?>> params) {
		String queryString = "from " + StringUtils.substringAfter(hql, "from");
		queryString = StringUtils.substringBefore(queryString, "order by");
		queryString = "select count(id) " + queryString;
		Query query = this.buildQuery(queryString, params);
		long recTotal = ((Long) query.iterate().next()).longValue();
		return recTotal;
	}

	public long getCountByHQL(final String hql, Object... params) {
		Query query = this.buildQuery(hql, params);
		long recTotal = (Long) query.iterate().next();
		return recTotal;
	}
	
	public Object getSingleResult(List<?> resultList){
		if(null!=resultList&&resultList.size()>0){
			return resultList.get(0);
		}
		return null;
	}
}
